using DG.Tweening;
using TMPro;
using Unity.VisualScripting;
using UnityEngine;
using UnityEngine.Events;
using UnityEngine.EventSystems;
using UnityEngine.UI;
namespace NuoYan.Extension
{
    public class ButtonEx : Selectable, IPointerDownHandler, IPointerUpHandler,IPointerClickHandler,IPointerEnterHandler,IPointerMoveHandler,IPointerExitHandler,IBeginDragHandler,IEndDragHandler,IDragHandler
    {
        [SerializeField]protected bool CanDrag = false; //是否可以拖拽,拖拽时将不会执行点击事件
        [SerializeField,Tooltip("是否忽略其他脚本对物体缩放的修改")] protected bool ignoreOtherScaleChange = false; //是否忽略其他脚本对物体缩放的修改
        protected bool isDragging = false;
        [Tooltip("CanDrag为true时,需要根据物体的类型设置，UI，需要将物体放在Canvas下，ObjectType2D，需要将摄像机设置为透视模式，ObjectType3D，需要将摄像机设置为正交模式")]
        [SerializeField]protected ObjectType objectType = ObjectType.UI;
        [SerializeField]protected MouseType mouseType = MouseType.LeftButton;
        [SerializeField]protected ClickScale clickScale;
        private Vector2 originScale;
        public TextMeshProUGUI textMeshProUGUI;
        public Text text;
        public bool wasPressed;
        public bool wasHovered;
        [Space(10)]
        public UnityEvent onPress;
        public UnityEvent onHover;
        public UnityEvent onClick;
        public UnityEvent onUp;
        public UnityEvent onDown;
        /// <summary>
        /// 与onClick同级
        /// </summary>
        public UnityEvent<bool> onValueChange;
        

        protected override void OnEnable()
        {
            base.OnEnable();
            wasHovered = false;
            wasPressed = false;
            if(ignoreOtherScaleChange == true)
            {
                originScale = transform.localScale;
                clickScale.enterScale = originScale.x;
                clickScale.clickScale = originScale.x;
            }
            
            if(Camera.main != null)
            {
                Camera.main.gameObject.GetOrAddComponent<PhysicsRaycaster>();
                Camera.main.gameObject.GetOrAddComponent<Physics2DRaycaster>();
            }
            FindText();
            Object2DColorUpdate(colors.normalColor);
        }
        protected override void OnDisable() 
        {
            base.OnDisable();
            wasHovered = false;
            wasPressed = false;
            Object2DColorUpdate(colors.normalColor);
        }
        protected virtual void Update() 
        {
            if (wasPressed)
            {
                onPress?.Invoke();
            }
            if (wasHovered)
            {
                onHover?.Invoke();
            }
        }

        /// <summary>
        /// Image时默认使用Unity内部点击颜色变化，默认左键
        /// </summary>
        /// <param name="color"></param>
        public virtual void Object2DColorUpdate(Color color)
        {
            if (objectType == ObjectType.Object2D && this.GetComponent<Image>() == null && transition == Selectable.Transition.ColorTint)
            {
                SpriteRenderer sp = GetComponent<SpriteRenderer>();
                if (sp != null)
                {
                    sp.color = color;
                }
            }
            
        }

        public virtual void ClickScaleUpdate(float scale)
        {
            if(ignoreOtherScaleChange == true)
            {
                transform.DOScale(scale, clickScale.duration);
            }
        }

        public override void OnPointerDown(PointerEventData eventData)
        {
            base.OnPointerDown(eventData);
            if(!interactable) return;
            switch (mouseType)
            {
                case MouseType.LeftButton:
                    HandleMouseButtonDown(MouseButton.Left);
                    break;
                case MouseType.RightButton:
                    HandleMouseButtonDown(MouseButton.Right);
                    break;
                case MouseType.MiddleButton:
                    HandleMouseButtonDown(MouseButton.Middle);
                    break;
            }
            
        }
        protected void HandleMouseButtonDown(MouseButton mouseButton)
        {
            if (Input.GetMouseButtonDown((int)mouseButton))
            {
                wasPressed = true;
                onDown?.Invoke();
                Object2DColorUpdate(colors.pressedColor);
                ClickScaleUpdate(clickScale.clickScale);
            }
        }


        public override void OnPointerUp(PointerEventData eventData)
        {
            base.OnPointerUp(eventData);
            if(!interactable) return;
            switch (mouseType)
            {
                case MouseType.LeftButton:
                    HandleMouseButtonUp(MouseButton.Left);
                    break;
                case MouseType.RightButton:
                    HandleMouseButtonUp(MouseButton.Right);
                    break;
                case MouseType.MiddleButton:
                    HandleMouseButtonUp(MouseButton.Middle);
                    break;
            }
            
        }
        protected void HandleMouseButtonUp(MouseButton mouseButton)
        {
            if (Input.GetMouseButtonUp((int)mouseButton))
            {
                wasPressed = false;
                onUp?.Invoke();
                Object2DColorUpdate(colors.pressedColor);
                ClickScaleUpdate(clickScale.enterScale);
            }
        }


        public virtual void OnPointerClick(PointerEventData eventData)
        {
            if(!interactable) return;
            if(isDragging) return;
            switch (mouseType)
            {
                case MouseType.LeftButton:
                    HandleMouseButtonClick(MouseButton.Left);
                    break;
                case MouseType.RightButton:
                    HandleMouseButtonClick(MouseButton.Right);
                    break;
                case MouseType.MiddleButton:
                    HandleMouseButtonClick(MouseButton.Middle);
                    break;
            }
        }
        protected void HandleMouseButtonClick(MouseButton mouseButton)
        {
            if (Input.GetMouseButtonUp((int)mouseButton))
            {
                onClick?.Invoke();
                onValueChange?.Invoke(true);
                Object2DColorUpdate(colors.selectedColor);
            }
        }

        public override void OnPointerEnter(PointerEventData eventData)
        {
            base.OnPointerEnter(eventData);
            if(!interactable) return;
            wasHovered = true;
            Object2DColorUpdate(colors.highlightedColor);
            ClickScaleUpdate(clickScale.enterScale);
        }
        public virtual void OnPointerMove(PointerEventData eventData)
        {

        }
        public override void OnPointerExit(PointerEventData eventData)
        {
            base.OnPointerExit(eventData);
            if(!interactable) return;
            wasHovered = false;
            wasPressed = false;
            Object2DColorUpdate(colors.normalColor);
            ClickScaleUpdate(originScale.x);
        }





        public virtual void OnBeginDrag(PointerEventData eventData)
        {
            
        }

        public virtual void OnEndDrag(PointerEventData eventData)
        {
            if(!interactable) return;
            isDragging = false;
        }

        public virtual void OnDrag(PointerEventData eventData)
        {
            if(!interactable) return;
            if(CanDrag)
            {
                switch (mouseType)
                {
                    case MouseType.LeftButton:
                        HandleDrag(MouseButton.Left);
                        break;
                    case MouseType.RightButton:
                        HandleDrag(MouseButton.Right);
                        break;
                    case MouseType.MiddleButton:
                        HandleDrag(MouseButton.Middle);
                        break;
                }
            }
        }
        private void HandleDrag(MouseButton mouseButton)
        {
            if (Input.GetMouseButton((int)mouseButton))
            {
                isDragging = true;
                switch (objectType)
                {
                    case ObjectType.UI:
                        Canvas canvas = GetComponentInParent<Canvas>();
                        
                        if (canvas != null)
                        {
                            if(canvas.renderMode == RenderMode.ScreenSpaceOverlay)
                            {
                                transform.position = Input.mousePosition; 
                            }
                            else if (canvas.renderMode == RenderMode.ScreenSpaceCamera || canvas.renderMode == RenderMode.WorldSpace)
                            {
                                // 将屏幕坐标转换为Canvas的本地坐标
                                RectTransformUtility.ScreenPointToLocalPointInRectangle(
                                    canvas.transform as RectTransform,
                                    Input.mousePosition,
                                    canvas.worldCamera,
                                    out Vector2 localPoint);
                                transform.localPosition = new Vector3(localPoint.x, localPoint.y, 0);
                            }
                            
                        }
                        break;
                    case ObjectType.Object3D:
                        float worldY = transform.localPosition.y;
                        Vector3 pos = new Vector3(Input.mousePosition.x, Input.mousePosition.y,Camera.main.WorldToScreenPoint(transform.position).z);
                        Vector3 worldPos = Camera.main.ScreenToWorldPoint(pos);
                        transform.localPosition = new Vector3(worldPos.x,worldY,worldPos.z);
                        break;
                    case ObjectType.Object2D:
                        transform.localPosition = InputExtension.MousePointToWorldPoint;
                        break;
                }
            }
        }

        private void FindText()
        {
            if(this.TryGetComponent<Text>(out Text text))
            {
                this.text = text;
            }
            if(this.TryGetComponent<TextMeshProUGUI>(out TextMeshProUGUI textMeshProUGUI))
            {
                this.textMeshProUGUI = textMeshProUGUI;
                Debug.Log(this.textMeshProUGUI);
            }
        }

    }
    /// <summary>
    /// 当CanDrag为true时，ObjectType会有影响，否则无影响
    /// </summary>
    public enum ObjectType
    {
        UI,
        /// <summary>
        /// 相机为透视相机时拖拽2D物体
        /// </summary>
        Object2D,
        Object3D
    }

    public enum MouseType
    {
        LeftButton,
        RightButton,
        MiddleButton,
    }
    [System.Serializable]
    public class ClickScale
    {
        [Range(0, 10)]
        public float enterScale = 1;
        [Range(0, 10)]
        public float clickScale = 1;
        [Range(0, 1)]
        public float duration = 0.5f    ;
    }
}

